package com.l2jserver.gameserver.datatables;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.PledgeImage;
import com.l2jserver.util.Rnd;

/**
 * Cargamos a la memoria imagenes albergadas en el servidor q usaremos en los html del mismo.<br>
 * Carga de Imagenes para el sistema de Ranking custom<br>
 * Carga de Imagenes para el sistema de VoteRewardIndividual<br>
 * Carga y encriptacion de imagenes para el sistema de AntiBot<br>
 * Carga de Imagenes para el casino<br>
 * @author fissban
 */
public final class ImagesTables
{
	public static Logger _log = Logger.getLogger(ImagesTables.class.getName());
	
	private static final Map<Integer, byte[]> _imageRank = new HashMap<>();
	private static final Map<Integer, byte[]> _imageVote = new HashMap<>();
	private static final Map<Integer, byte[]> _imageCasino = new HashMap<>();
	public static Map<Integer, antiBotData> _imageAntiBotOri = new HashMap<>();
	public static Map<Integer, antiBotData> _imageAntiBotClient = new HashMap<>();
	
	// @formatter:off
	public final int[] _img_slot_id =
	{
		9000, 9001, 9002, 9003, 9004, 9005, 9006, 9007, 9008, 9009,
		9010, 9011, 9012, 9013, 9014, 9015, 9016, 9017, 9018, 9019
	};

	private final int[] _img_blackJack_id =
	{
		9021, 9022, 9023, 9024, 9025, 9026, 9027, 9028, 9029, 9030, 9031, 9032, 9033,
		9041, 9042, 9043, 9044, 9045, 9046, 9047, 9048, 9049, 9050, 9051, 9052, 9053,
		9061, 9062, 9063, 9064, 9065, 9066, 9067, 9068, 9069, 9070, 9071, 9072, 9073,
		9081, 9082, 9083, 9084, 9085, 9086, 9087, 9088, 9089, 9090, 9091, 9092, 9093,
		9020
	};
	
	private final int[] img_rank_id =
	{
		5000, 5001,	5002, 5003,	5004, 5005,	5010, 5011,	5012, 5013,	5014, 5015,	5020, 5021,
		5022, 5023,	5024, 5025,	5030, 5031,	5032, 5033,	5034, 5035,	5040, 5041,	5042, 5043,
		5044, 5045
	};

	private final int[] img_vote_id =
	{
		6000, 6001, 6002, 6003
	};

	public final static int[] img_antibot_id =
	{
		7000, 7001, 7002, 7003, 7004, 7005, 7006, 7007, 7008, 7009
	};
	// @formatter:on
	
	/**
	 * Cargamos las imagenes a la memoria
	 */
	public void loadImage()
	{
		LoadImgRank();
		LoadImgVote();
		LoadImgAntiBot();
		LoadImgCasino();
		
		_log.log(Level.INFO, "loading " + _imageRank.size() + " images of Ranking");
		_log.log(Level.INFO, "loading " + _imageVote.size() + " images of VoteIndividual");
		_log.log(Level.INFO, "loading " + _imageAntiBotOri.size() + " images of AntiBot");
		_log.log(Level.INFO, "loading " + _imageCasino.size() + " images of Casino");
	}
	
	private void LoadImgCasino()
	{
		_imageCasino.clear();
		
		for (int imgId : _img_slot_id)
		{
			File image = new File("data/images/casino/SlotMachine/" + imgId + ".dds");
			_imageCasino.put(imgId, ConverterImgBytes(image));
		}
		for (int imgId : _img_blackJack_id)
		{
			File image = new File("data/images/casino/BlackJack/" + imgId + ".dds");
			_imageCasino.put(imgId, ConverterImgBytes(image));
		}
	}
	
	private void LoadImgRank()
	{
		_imageRank.clear();
		for (int imgId : img_rank_id)
		{
			File image = new File("data/images/rank/" + imgId + ".dds");
			_imageRank.put(imgId, ConverterImgBytes(image));
		}
	}
	
	private void LoadImgVote()
	{
		_imageVote.clear();
		for (int imgId : img_vote_id)
		{
			File image = new File("data/images/vote/" + imgId + ".dds");
			_imageVote.put(imgId, ConverterImgBytes(image));
		}
	}
	
	private void LoadImgAntiBot()
	{
		_imageAntiBotOri.clear();
		int cont = 0;
		
		for (int imgId : img_antibot_id)
		{
			File image = new File("data/images/antibot/" + imgId + ".dds");
			_imageAntiBotOri.put(cont, new antiBotData(cont, ConverterImgBytes(image)));
			cont++;
		}
		
		ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new startEncriptCaptcha(), 100, 600000); // 10 min
	}
	
	/**
	 * Usado para enviar la imagen al char.
	 * @param player
	 * @param imgId
	 */
	public void sendImage(L2PcInstance player, int imgId)
	{
		PledgeImage packet = null;
		
		// shift+click ranking
		if ((imgId >= 5000) && (imgId < 6000))
		{
			packet = new PledgeImage(imgId, _imageRank.get(imgId));
		}
		// Npc VoteIndividual
		else if ((imgId >= 6000) && (imgId < 7000))
		{
			packet = new PledgeImage(imgId, _imageVote.get(imgId));
		}
		// Casino
		else if ((imgId >= 9000) && (imgId < 10000))
		{
			packet = new PledgeImage(imgId, _imageCasino.get(imgId));
		}
		// Antibot
		else if ((imgId >= 50000) && (imgId <= 800000))
		{
			for (Entry<Integer, antiBotData> entrySet : _imageAntiBotClient.entrySet())
			{
				antiBotData imgCoding = entrySet.getValue();
				
				if (imgId == imgCoding.getCodificacion())
				{
					packet = new PledgeImage(imgId, imgCoding.getImagen());
				}
			}
		}
		
		player.sendPacket(packet);
	}
	
	/**
	 * Sistema de encritpacion de imagenes para el sistema de AntiBot
	 */
	public static class startEncriptCaptcha implements Runnable
	{
		public startEncriptCaptcha()
		{
		}
		
		@Override
		public void run()
		{
			_imageAntiBotClient.clear();
			
			for (Entry<Integer, antiBotData> entrySet : _imageAntiBotOri.entrySet())
			{
				entrySet.getValue().getImagen();
				_imageAntiBotClient.put(entrySet.getKey(), new antiBotData(Rnd.get(50000, 800000), entrySet.getValue().getImagen()));
			}
		}
	}
	
	/**
	 * @param pos
	 * @return segun el valor el pos, devuelve el ID correspondiente al numero "pos" ingresado
	 */
	public int getAntiBotClientID(int pos)
	{
		int returnCoding = 0;
		
		for (Entry<Integer, antiBotData> entrySet : _imageAntiBotClient.entrySet())
		{
			int numeroImage = entrySet.getKey().intValue(); // numero
			
			if (pos == numeroImage)
			{
				antiBotData imgCoding = entrySet.getValue();
				returnCoding = imgCoding.getCodificacion();// codificacion
			}
			
			// Nunca deberia pasar!
			if (pos > 9)
			{
				_log.log(Level.SEVERE, "error in getAntiBotClientID...number dont exist");
			}
		}
		return returnCoding;
	}
	
	public static class antiBotData
	{
		int _codificacion;
		byte[] _data;
		
		public antiBotData(int codificacion, byte[] data)
		{
			_codificacion = codificacion;
			_data = data;
		}
		
		public int getCodificacion()
		{
			return _codificacion;
		}
		
		public byte[] getImagen()
		{
			return _data;
		}
	}
	
	/**
	 * @param imagen a convertir (File)
	 * @return imagen en byte[]
	 */
	private static byte[] ConverterImgBytes(File imagen)
	{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		
		byte[] buffer = new byte[1024];
		try (FileInputStream fis = new FileInputStream(imagen))
		{
			for (int readNum; (readNum = fis.read(buffer)) != -1;)
			{
				bos.write(buffer, 0, readNum);
			}
		}
		catch (IOException e)
		{
			_log.log(Level.SEVERE, "Error when converter image to byte[]");
			
		}
		
		return bos.toByteArray();
	}
	
	public static ImagesTables getInstance()
	{
		return SingletonHolder._instance;
	}
	
	private static class SingletonHolder
	{
		protected static final ImagesTables _instance = new ImagesTables();
	}
}